




#include "mcu_soft_pwm.h"


//#include<math.h>



/// <summary>
/// 用计数周期和高电平计数数量来初始化pwm结构体。
/// 初始电平是1，初始计数模式：向上计数。（不可更改）
/// </summary>
/// <param name="sp">pwm 的结构体</param>
/// <param name="count_period"> 设定计数周期，最小是2，对应的pwm频率 =  </param>
/// <param name="high_level_in_count_period"> 设定高电平中计数周期的数量，必须小于计数周期，占空比=high_level_in_count_period/count_period </param>
/// <param name="is_Centrosymmetric">波形是否中心对称的</param>
void soft_pwm_init(soft_pwm* sp, int count_period, int high_level_in_count_period, bool is_Centrosymmetric) // 下面初始化pwm的参数
{
	sp->Timer_us = Soft_PWM_Timer_us;   // 定时器调用间隔，微秒。	
	sp->Counter = 0;    // 当前的计数。这个计数只会在 0 - (Counter_Period-1)之间	

	sp->Counter_Mode = true;      // 计数模式，默认1，向上。如果是0，向下。
	sp->Polarity = true;          // 极性。到达比较计数，会改变极性。

	if (is_Centrosymmetric)
		sp->Central_Symmetry = true;
	else
		sp->Central_Symmetry = false;

	// 如果是中心对称模式，占空比是不会变的，但示波器测量，频率会减半。
	// 原来两个周期是：00111 00111 ，为了中心对称，计数器到达计数周期，会改变计数模式，
	// 第二个周期改为向下计数： 变成 00111 11100，周期初始极性也改变了。

	if (count_period < 2)count_period = 2;
	if (high_level_in_count_period > count_period)high_level_in_count_period = count_period;

	if (high_level_in_count_period <= 0)sp->Polarity = false;   // 如果占空比小于0，就一直显示是0

	sp->Counter_Period = count_period;

	sp->Compare = high_level_in_count_period;
}
//

/// <summary>
/// 模拟pwm 的时钟，间隔sp->Timer_us调用一次。
/// sp->Polarity 会表示当前时刻的电平（极性0或1）
/// </summary>
/// <param name="sp">pwm 的结构体</param>
void soft_pwm_clock(soft_pwm* sp)
{
//	bool is_change_polarity = false;
	if (sp->Compare == 0) {
		sp->Polarity = false;
	}
	else if (sp->Compare == sp->Counter_Period) {
		sp->Polarity = true;
	}
	else {
		if (sp->Counter_Mode) {
			sp->Counter++;
			if (sp->Central_Symmetry == false) {	 // 不是对称模式。	
				if (sp->Counter == sp->Compare) {
					sp->Polarity = (sp->Polarity == true ? false : true);
				}
				if (sp->Counter == sp->Counter_Period) {
					sp->Counter = 0;
					sp->Polarity = (sp->Polarity == true ? false : true);
				}
			}
			else {   // 对称模式
				if (sp->Counter == sp->Compare) {
					sp->Polarity = (sp->Polarity == true ? false : true);
				}
				if (sp->Counter == sp->Counter_Period) {
					sp->Counter_Mode = false;
				}
			}
		}
		else {
			sp->Counter--;
			if (sp->Central_Symmetry == false) {	 // 不是对称模式。			
				if ((sp->Counter) == sp->Compare) {
					sp->Polarity = (sp->Polarity == true ? false : true);
				}
				if (sp->Counter == 0) {
					sp->Counter = sp->Counter_Period;
					sp->Polarity = (sp->Polarity == true ? false : true);
				}
			}
			else {   // 对称模式
				if ((sp->Counter) == sp->Compare) {
					sp->Polarity = (sp->Polarity == true ? false : true);
				}
				if (sp->Counter == 0) {
					sp->Counter_Mode = true;
				}
			}
		}
	}
}
//
#include"gl_.h"  //用于测试产生的波形
// 下面绘图测试pwm。向上计数的对称，非对称pwm都测了，没问题。
void test_soft_pwm()
{
	soft_pwm sp;

#define t_len  50
	float t[t_len];
	float o[t_len];


	TwoFunctionPicture tp;
	TwoFunctionPicture_init(&tp, 0, 0, 700, 450);
	char title[] = "Curve Chart";          //标题
	char xtitle[] = "xtitle time";          //x轴标题
	char y1title[] = "y1title cm";          //y轴标题
	char y2title[] = "y2title km";          //y轴标题
	TwoFunctionPicture_draw_title(&tp, title, xtitle, y1title, y2title);
	for (int duty = 0; duty < 12; duty++) {

		soft_pwm_init(&sp, 10, duty, 0);
		for (int i = 0; i < t_len; i++) {
			t[i] = i;
			o[i] = sp.Polarity ? 1 : 0;
			soft_pwm_clock(&sp);
		}

		// 绘图显示。
		TwoFunctionPicture_draw_func(&tp,
			t, o, t_len,
			NULL, NULL, 0,
			1, 0, 0, NULL, NULL);

		printfs("  \r\n  P = %d, duty = %d ", 10, duty);

		GD_wait_key_input();	// 按任意键继续
	}

	GD_wait_key_input();
}






